#!/usr/bin/python
# coding:utf-8
__author__ = 'good'
__createday__ = '2015-01-14'

import datetime
from golsee import db
from flask_login import AnonymousUserMixin

USER_LOCKED = 0

RANDOM_PASSWORD_LENGTH = 5


class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    nicename = db.Column(db.String(64), index=True, unique=True)
    passwd = db.Column(db.String(128))
    email = db.Column(db.String(128), index=True, unique=True)
    info = db.Column(db.String(140))
    url = db.Column(db.String(100))
    is_locked = db.Column(db.Integer, default=USER_LOCKED)
    last_seen = db.Column(db.DateTime)
    register_date = db.Column(db.DateTime)
    register_ip = db.Column(db.String(15))
    articles = db.relationship('Article', backref='author', lazy='dynamic')
    User_ext = db.relationship('User_ext', backref='user', lazy='dynamic')
    role = db.Column(db.Integer, db.ForeignKey('role.id'), nullable=False)

    def __init__(self, email, nicename, info=None, url=None, register_ip=None):
        self.email = email
        self.nicename = nicename
        self.info = info
        self.url = url
        self.register_ip = register_ip
        self.register_date = datetime.datetime.now()
        self.role = Role.query.filter_by(default=True).first().id

    def is_authenticated(self):
        return True

    def is_active(self):
        if self.is_locked == 0:
            return True
        else:
            return False

    def is_anonymous(self):
        return False

    def can(self, permissions):
        return self.role is not None and (self.roles.permissions & permissions) == permissions

    def is_admin(self):
        return self.can(Permission.ADMINISTER)

    def get_id(self):
        return unicode(self.id)

    def avatar(self, size):
        from hashlib import md5

        md5str = md5(self.email).hexdigest()
        return 'https://secure.gravatar.com/avatar/' + md5str + '?d=mm&s=' + str(size)

    def __repr__(self):
        return '<User %r>' % (self.nicename)

    def set_password(self, password):
        from werkzeug.security import generate_password_hash

        self.passwd = generate_password_hash(password)

    def check_password(self, password):
        from werkzeug.security import check_password_hash

        return check_password_hash(self.passwd, password)

    @classmethod
    def is_email_use(cls, email):
        user = User.query.filter_by(email=email).first()
        if user:
            return True

    @classmethod
    def count_all(cls):
        count = db.session.query(db.func.count(User.id).label('user_all')).first().user_all
        return count


class User_ext(db.Model):
    __tablename__ = 'user_ext'
    id = db.Column(db.INTEGER, primary_key=True)
    theme = db.Column(db.String(20))
    view_num = db.Column(db.INTEGER)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)


class AnonymousUser(AnonymousUserMixin):
    def can(self, permissions):
        return False

    def is_administrator(self):
        return False


class Role(db.Model):
    __tablename__ = 'role'
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(50), unique=True)
    default = db.Column(db.Boolean, default=False, index=True)
    permissions = db.Column(db.Integer)
    user = db.relationship('User', backref='roles', lazy='dynamic')

    @staticmethod
    def insert_roles():
        roles = {'User': (Permission.LOGIN |
                          Permission.COMMENT,
                          True),
                 'Writer': (Permission.LOGIN |
                            Permission.COMMENT |
                            Permission.WRITE_ARTICLES,
                            False),
                 'Administrator': (0xff, False)}
        for r in roles:
            role = Role.query.filter_by(name=r).first()
            if role is None:
                role = Role(name=r)
            role.permissions = roles[r][0]
            role.default = roles[r][1]
            db.session.add(role)
            db.session.commit()


class Permission:
    LOGIN = 0x01
    COMMENT = 0x02
    WRITE_ARTICLES = 0x04
    ADMINISTER = 0x80


